# -*- coding: utf-8 -*-
# Author   : ZhangQing
# Time     : 2025-08-05 23:29
# File     : user.py
# Project  : codebuddy_craft
# Desc     :
# backend/schemas/user.py
# backend/schemas/user.py
"""
用户数据模式定义 👤

定义用户相关的请求和响应数据结构
"""

from pydantic import BaseModel, Field, EmailStr, validator
from typing import Optional, Dict, Any, List
from datetime import datetime


class UserResponse(BaseModel):
    """用户响应模型 👤"""
    id: str = Field(..., description="用户ID")
    username: str = Field(..., description="用户名")
    email: str = Field(..., description="邮箱地址")
    full_name: Optional[str] = Field(None, description="全名")
    avatar_url: Optional[str] = Field(None, description="头像URL")
    is_active: bool = Field(..., description="是否激活")
    is_verified: bool = Field(..., description="是否已验证")
    preferences: Dict[str, Any] = Field(default_factory=dict, description="用户偏好")
    created_at: Optional[datetime] = Field(None, description="创建时间")
    updated_at: Optional[datetime] = Field(None, description="更新时间")
    last_login_at: Optional[datetime] = Field(None, description="最后登录时间")

    class Config:
        from_attributes = True
        json_encoders = {
            datetime: lambda v: v.isoformat() if v else None
        }

    @classmethod
    def from_orm(cls, obj):
        """从ORM对象创建响应模型 🔄"""
        if not obj:
            return None

        return cls(
            id=obj.id,
            username=obj.username,
            email=obj.email,
            full_name=obj.full_name,
            avatar_url=obj.avatar_url,
            is_active=obj.is_active,
            is_verified=obj.is_verified,
            preferences=obj.preferences or {},
            created_at=obj.created_at,
            updated_at=obj.updated_at,
            last_login_at=obj.last_login_at
        )

    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式 📖"""
        return {
            "id": self.id,
            "username": self.username,
            "email": self.email,
            "full_name": self.full_name,
            "avatar_url": self.avatar_url,
            "is_active": self.is_active,
            "is_verified": self.is_verified,
            "preferences": self.preferences,
            "created_at": self.created_at.isoformat() if self.created_at else None,
            "updated_at": self.updated_at.isoformat() if self.updated_at else None,
            "last_login_at": self.last_login_at.isoformat() if self.last_login_at else None
        }

    def get_display_name(self) -> str:
        """获取显示名称 📝"""
        return self.full_name or self.username

    def get_avatar_url(self, size: int = 80) -> str:
        """获取头像URL 🖼️"""
        if self.avatar_url:
            return self.avatar_url

        # 生成默认头像URL (使用Gravatar)
        import hashlib
        email_hash = hashlib.md5(self.email.lower().encode()).hexdigest()
        return f"https://www.gravatar.com/avatar/{email_hash}?s={size}&d=identicon"

    def is_online(self) -> bool:
        """判断用户是否在线 🟢"""
        if not self.last_login_at:
            return False

        from datetime import datetime, timedelta
        # 如果5分钟内有活动则认为在线
        return (datetime.utcnow() - self.last_login_at) < timedelta(minutes=5)

    def get_join_duration(self) -> str:
        """获取加入时长 ⏱️"""
        if not self.created_at:
            return "未知"

        from datetime import datetime
        duration = datetime.utcnow() - self.created_at.replace(tzinfo=None)

        if duration.days > 365:
            years = duration.days // 365
            return f"{years}年前加入"
        elif duration.days > 30:
            months = duration.days // 30
            return f"{months}个月前加入"
        elif duration.days > 0:
            return f"{duration.days}天前加入"
        else:
            hours = duration.seconds // 3600
            return f"{hours}小时前加入"


class UserUpdateRequest(BaseModel):
    """用户更新请求模型 ✏️"""
    full_name: Optional[str] = Field(None, max_length=100, description="全名")
    email: Optional[EmailStr] = Field(None, description="邮箱地址")
    avatar_url: Optional[str] = Field(None, max_length=255, description="头像URL")
    preferences: Optional[Dict[str, Any]] = Field(None, description="用户偏好")

    @validator('full_name')
    def validate_full_name(cls, v):
        """验证全名"""
        if v:
            v = v.strip()
            if len(v) < 1:
                raise ValueError("全名不能为空")
        return v

    @validator('avatar_url')
    def validate_avatar_url(cls, v):
        """验证头像URL"""
        if v:
            import re
            # 支持更多图片格式和域名
            url_pattern = r'^https?://[^\s/$.?#].[^\s]*\.(jpg|jpeg|png|gif|webp|svg)(\?[^\s]*)?$'
            if not re.match(url_pattern, v, re.IGNORECASE):
                raise ValueError('头像URL格式不正确，请提供有效的图片链接')
        return v

    @validator('preferences')
    def validate_preferences(cls, v):
        """验证用户偏好设置"""
        if v:
            # 检查偏好设置的合法性
            allowed_keys = {
                'theme', 'language', 'timezone', 'notifications',
                'editor_settings', 'privacy_settings'
            }

            for key in v.keys():
                if key not in allowed_keys:
                    raise ValueError(f"不支持的偏好设置: {key}")

            # 验证主题设置
            if 'theme' in v and v['theme'] not in ['light', 'dark', 'auto']:
                raise ValueError("主题设置必须是: light, dark, auto")

            # 验证语言设置
            if 'language' in v and v['language'] not in ['zh-CN', 'en-US', 'zh-TW']:
                raise ValueError("语言设置必须是: zh-CN, en-US, zh-TW")

        return v


class UserSearchResponse(BaseModel):
    """用户搜索响应模型 🔍"""
    id: str = Field(..., description="用户ID")
    username: str = Field(..., description="用户名")
    full_name: Optional[str] = Field(None, description="全名")
    avatar_url: Optional[str] = Field(None, description="头像URL")
    is_verified: bool = Field(..., description="是否已验证")
    created_at: Optional[datetime] = Field(None, description="创建时间")

    class Config:
        from_attributes = True
        json_encoders = {
            datetime: lambda v: v.isoformat() if v else None
        }

    @classmethod
    def from_orm(cls, obj):
        """从ORM对象创建搜索响应模型"""
        return cls(
            id=obj.id,
            username=obj.username,
            full_name=obj.full_name,
            avatar_url=obj.avatar_url,
            is_verified=obj.is_verified,
            created_at=obj.created_at
        )

    def get_display_name(self) -> str:
        """获取显示名称"""
        return self.full_name or self.username


class UserProfileResponse(BaseModel):
    """用户详细资料响应模型 📋"""
    id: str = Field(..., description="用户ID")
    username: str = Field(..., description="用户名")
    email: str = Field(..., description="邮箱地址")
    full_name: Optional[str] = Field(None, description="全名")
    avatar_url: Optional[str] = Field(None, description="头像URL")
    is_active: bool = Field(..., description="是否激活")
    is_verified: bool = Field(..., description="是否已验证")
    preferences: Dict[str, Any] = Field(default_factory=dict, description="用户偏好")
    created_at: Optional[datetime] = Field(None, description="创建时间")
    updated_at: Optional[datetime] = Field(None, description="更新时间")
    last_login_at: Optional[datetime] = Field(None, description="最后登录时间")

    # 统计信息
    project_count: Optional[int] = Field(None, description="项目数量")
    total_lines: Optional[int] = Field(None, description="总代码行数")
    total_files: Optional[int] = Field(None, description="总文件数量")
    collaborations: Optional[int] = Field(None, description="协作项目数量")

    class Config:
        from_attributes = True
        json_encoders = {
            datetime: lambda v: v.isoformat() if v else None
        }

    @classmethod
    def from_orm(cls, obj, stats: Optional[Dict[str, Any]] = None):
        """从ORM对象创建详细资料响应模型"""
        data = {
            "id": obj.id,
            "username": obj.username,
            "email": obj.email,
            "full_name": obj.full_name,
            "avatar_url": obj.avatar_url,
            "is_active": obj.is_active,
            "is_verified": obj.is_verified,
            "preferences": obj.preferences or {},
            "created_at": obj.created_at,
            "updated_at": obj.updated_at,
            "last_login_at": obj.last_login_at
        }

        # 添加统计信息
        if stats:
            data.update(stats)

        return cls(**data)


class UserListResponse(BaseModel):
    """用户列表响应模型 📋"""
    items: List[UserSearchResponse] = Field(..., description="用户列表")
    total: int = Field(..., description="用户总数")
    skip: int = Field(default=0, description="跳过数量")
    limit: int = Field(default=20, description="返回数量")

    class Config:
        from_attributes = True


class UserStatsResponse(BaseModel):
    """用户统计响应模型 📊"""
    user_id: str = Field(..., description="用户ID")
    username: str = Field(..., description="用户名")
    project_count: int = Field(..., description="项目数量")
    total_lines: int = Field(..., description="总代码行数")
    total_files: int = Field(..., description="总文件数量")
    collaborations: int = Field(..., description="协作项目数量")
    favorite_languages: List[Dict[str, Any]] = Field(default_factory=list, description="常用编程语言")
    activity_stats: Dict[str, Any] = Field(default_factory=dict, description="活动统计")
    join_date: Optional[str] = Field(None, description="加入日期")
    last_active: Optional[str] = Field(None, description="最后活跃时间")

    class Config:
        from_attributes = True


class UserPreferencesUpdate(BaseModel):
    """用户偏好设置更新模型 ⚙️"""
    theme: Optional[str] = Field(None, description="主题设置")
    language: Optional[str] = Field(None, description="语言设置")
    timezone: Optional[str] = Field(None, description="时区设置")
    notifications: Optional[Dict[str, bool]] = Field(None, description="通知设置")
    editor_settings: Optional[Dict[str, Any]] = Field(None, description="编辑器设置")
    privacy_settings: Optional[Dict[str, bool]] = Field(None, description="隐私设置")

    @validator('theme')
    def validate_theme(cls, v):
        """验证主题设置"""
        if v and v not in ['light', 'dark', 'auto']:
            raise ValueError("主题设置必须是: light, dark, auto")
        return v

    @validator('language')
    def validate_language(cls, v):
        """验证语言设置"""
        if v and v not in ['zh-CN', 'en-US', 'zh-TW']:
            raise ValueError("语言设置必须是: zh-CN, en-US, zh-TW")
        return v

    @validator('notifications')
    def validate_notifications(cls, v):
        """验证通知设置"""
        if v:
            allowed_keys = {
                'email_notifications', 'push_notifications',
                'project_updates', 'collaboration_invites',
                'security_alerts', 'weekly_digest'
            }
            for key in v.keys():
                if key not in allowed_keys:
                    raise ValueError(f"不支持的通知设置: {key}")
        return v

    @validator('editor_settings')
    def validate_editor_settings(cls, v):
        """验证编辑器设置"""
        if v:
            allowed_keys = {
                'font_size', 'font_family', 'tab_size', 'word_wrap',
                'line_numbers', 'minimap', 'auto_save', 'vim_mode'
            }
            for key in v.keys():
                if key not in allowed_keys:
                    raise ValueError(f"不支持的编辑器设置: {key}")

            # 验证字体大小
            if 'font_size' in v:
                font_size = v['font_size']
                if not isinstance(font_size, int) or font_size < 10 or font_size > 24:
                    raise ValueError("字体大小必须在10-24之间")

            # 验证缩进大小
            if 'tab_size' in v:
                tab_size = v['tab_size']
                if not isinstance(tab_size, int) or tab_size < 2 or tab_size > 8:
                    raise ValueError("缩进大小必须在2-8之间")

        return v

    @validator('privacy_settings')
    def validate_privacy_settings(cls, v):
        """验证隐私设置"""
        if v:
            allowed_keys = {
                'profile_public', 'show_email', 'show_projects',
                'allow_collaboration_invites', 'show_activity'
            }
            for key in v.keys():
                if key not in allowed_keys:
                    raise ValueError(f"不支持的隐私设置: {key}")
        return v
